#include "StdAfx.h"
#include "LitScriptContext.h"
#include "LitScriptEngine.h"
#include "LitString.h"

namespace Lit
{
	/*/////////////////////////////////////
				SCRIPT
	/////////////////////////////////////*/
	ScriptContext::ScriptContext(const Ptr &context, RefPtr<ScriptEngine> engine)
	{
		mEngine = engine;
		mContext = context;
		mState = SCS_EXECUTION_UNINITIALIZED;
		mCreated = context?true:false;
	}
	
	ScriptContext::ScriptContext(const ScriptContext& rhs)
		: mEngine( rhs.mEngine )
		, mContext( rhs.mContext )
		, mCreated(rhs.mCreated)
		, mState( rhs.mState )
	{
	}

	ScriptContext::~ScriptContext(void)
	{
	}

	ScriptContextState ScriptContext::execute( )
	{
		if( !mContext || !mCreated || mState == SCS_EXECUTION_UNINITIALIZED )
		{
			throw ScriptInvalidContext( EXC_LOC );
		}
		mState = SCS_EXECUTION_ACTIVE;
		return (mState=(ScriptContextState)mContext->Execute());
	}
	ScriptContextState ScriptContext::getState() const{ return mState; }
	size_t ScriptContext::getLastExceptionLine() const{ if(!mContext) return 0; return mContext->GetExceptionLineNumber(); }
	std::string ScriptContext::getLastException() const{ if(!mContext) return ""; return mContext->GetExceptionString(); }
	std::string ScriptContext::getLastExceptionFunction() const{ if(!mContext) return ""; return mContext->GetExceptionFunction()->GetName(); }

	void ScriptContext::create()
	{ if( !mContext && mEngine && mEngine->data() ){ mContext = mEngine->data()->CreateContext(); mCreated = true; mState = SCS_EXECUTION_SUSPENDED; }}
	void ScriptContext::release()
	{ if(mContext)mContext->Release(); mCreated=false; mState = SCS_EXECUTION_UNINITIALIZED; }
	
	const RefPtr<ScriptEngine>& ScriptContext::getEngine() const{ return mEngine; }
	RefPtr<ScriptEngine>& ScriptContext::getEngine(){ return mEngine; }

	const ScriptContext::Ptr& ScriptContext::data() const{ return mContext; }
	ScriptContext::Ptr& ScriptContext::data(){ return mContext; }
	
	int ScriptContext::prepare(ScriptFunctionPtr& func)
	{
		assert( func && mContext );
		int r = mContext->Prepare( *func );
		if( r >= 0 ) mState = SCS_EXECUTION_PREPARED;
		return r;
	}
};